package com.ptu.spzx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ptu.spzx.common.exception.ptuException;
import com.ptu.spzx.domain.Class.Classes;
import com.ptu.spzx.domain.Course.Course;
import com.ptu.spzx.domain.Delete.DeleteIds;
import com.ptu.spzx.domain.Exam.Exam;
import com.ptu.spzx.domain.Exam.ExamClass;
import com.ptu.spzx.domain.Exam.ExamExampaper;
import com.ptu.spzx.domain.Exam.Exampaper;
import com.ptu.spzx.domain.Exam.dto.ExamDTO;
import com.ptu.spzx.domain.Exam.vo.*;
import com.ptu.spzx.domain.Question.po.Question;
import com.ptu.spzx.domain.Stu.StuAnswer;
import com.ptu.spzx.feign.userInfo.ManagerFeignClient;
import com.ptu.spzx.mapper.*;
import com.ptu.spzx.model.entity.system.SysUser;
import com.ptu.spzx.model.vo.common.ResultCodeEnum;
import com.ptu.spzx.service.IExamClassService;
import com.ptu.spzx.service.IExamExampaperService;
import com.ptu.spzx.service.IExamService;
import com.ptu.spzx.model.entity.user.UserInfo;
import com.ptu.spzx.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author YT
 * @since 2024-01-28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements IExamService {
    private final IExamClassService iExamClassService;
    private final IExamExampaperService iExamExampaperService;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ManagerFeignClient managerFeignClient;

    @Autowired
    private ExamClassMapper examClassMapper;

    @Autowired
    private StuAnswerMapper stuAnswerMapper;

    @Autowired
    private ExamExampaperMapper examExampaperMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ExampaperMapper exampaperMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionExampaperMapper questionExampaperMapper;

    //  添加考试
    @Override
    public void addExam(ExamDTO examDTO) {
        if (examDTO.getSemester() == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        Exam exams = new Exam();
        List<ExamClass> stuExams1 = new ArrayList<>();
        List<ExamExampaper> examExamPapers = new ArrayList<>();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date publishTime = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            publishTime = df.parse(examDTO.getExamPublishTime());
            beginTime = df.parse(examDTO.getExamBeginTime());
            endTime = df.parse(examDTO.getExamEndTime());
            if (publishTime.getTime() - beginTime.getTime() > 0) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
            if (beginTime.getTime() - endTime.getTime() > 0) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
        }

        exams.setCourseId(examDTO.getCourseId());
        exams.setExamName(examDTO.getExamName());
        exams.setExamPublishTime(examDTO.getExamPublishTime());
        exams.setExamBeginTime(examDTO.getExamBeginTime());
        exams.setExamEndTime(examDTO.getExamEndTime());
        exams.setExamDescription(examDTO.getExamDescription());
        exams.setSemester(examDTO.getSemester());
        examMapper.insert(exams);
        for (Long classId : examDTO.getClassId()) {
            ExamClass examClass = new ExamClass();
            examClass.setClassId(classId);
            examClass.setExamId(exams.getExamId());
            stuExams1.add(examClass);
        }
        iExamClassService.saveBatch(stuExams1);
        for (Long EpId : examDTO.getExamPaperId()) {
            ExamExampaper examPapers = new ExamExampaper();
            examPapers.setExamId(exams.getExamId());
            examPapers.setEpId(EpId);
            examExamPapers.add(examPapers);
        }
        iExamExampaperService.saveBatch(examExamPapers);
        try {
            if (examDTO.getCourseId() == null) {
                throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
            }
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.DATA_ERROR);
        }
        //定时器更新题目
        Timer timer = new Timer();
        TimerTask startTask = new TimerTask() {
            @Override
            public void run() {
                List<Long> examPaperIds = examDTO.getExamPaperId();
                for (Long epId : examPaperIds) {
                    List<Long> questionIds = questionExampaperMapper.selectByEpId(epId);
//           更新题目时间
                    // 获取当前时间
                    LocalDateTime currentTime = LocalDateTime.now();
                    // 定义日期时间格式化器
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    // 将当前时间格式化为字符串
                    String formattedDateTime = currentTime.format(formatter);
                    UpdateWrapper<Question> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.in("question_id", questionIds);
                    updateWrapper.set("used_time", formattedDateTime);
                    questionMapper.update(null, updateWrapper);
                }
            }
        };
        try{
            long current = System.currentTimeMillis();
            long startDelay = beginTime.getTime() - current;
            timer.schedule(startTask, startDelay);
        }catch (Exception e){
            throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
        }
    }

    //    删除考试
    @Override
    public void delExamById(DeleteIds deleteIds) {
        List<Long> ids = deleteIds.getIds();
        if (ids == null || ids.size() == 0) {
            throw new ptuException(ResultCodeEnum.PARAM_NULL);
        }
        for (Long examId : ids) {
            HashMap<String, Object> Mp = new HashMap<>();
            Mp.put("exam_id", examId);
            iExamExampaperService.removeByMap(Mp);
            iExamClassService.removeByMap(Mp);
            removeById(examId);
        }
    }

    //更新考试
    @Override
    public void updateExam(ExamDTO examDTO) {
        if (examDTO.getExamId() == null) {
            throw new ptuException(ResultCodeEnum.PARAM_NULL);
        }
        Exam exam = BeanCopyUtils.copyBean(examDTO, Exam.class);
        examMapper.updateById(exam);
        LambdaQueryWrapper<ExamExampaper> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ExamExampaper::getExamId, examDTO.getExamId());
        examExampaperMapper.delete(lambdaQueryWrapper);
        for (Long epId : examDTO.getExamPaperId()) {
            ExamExampaper examExampaper = new ExamExampaper();
            examExampaper.setExamId(examDTO.getExamId());
            examExampaper.setEpId(epId);
            examExampaperMapper.insert(examExampaper);
        }
        LambdaQueryWrapper<ExamClass> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.eq(ExamClass::getExamId, examDTO.getExamId());
        examClassMapper.delete(lambdaQueryWrapper2);
        for (Long classId : examDTO.getClassId()) {
            ExamClass examClass = new ExamClass();
            examClass.setClassId(classId);
            examClass.setExamId(examDTO.getExamId());
            examClassMapper.insert(examClass);
        }
    }


    //获取考试详细
    @Override
    public ExamVO getExamDetailById(Long id) {
        if (id == null) {
            throw new ptuException(ResultCodeEnum.PARAM_NULL);
        }
        Exam exam = examMapper.selectById(id);
        if (exam == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        ExamVO examVO = BeanCopyUtils.copyBean(exam, ExamVO.class);

//    班级更改
        List<Long> classIds = null;
        examVO.setClassId(classIds);
        List<Long> epIds = examExampaperMapper.selectByExamId(id);
        examVO.setExamPaperId(epIds);
        return examVO;
    }

    @Override
    public PageInfo<Exam> getExamByCourseIdSemester(Integer courseId, String semester, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Exam> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(courseId != null, Exam::getCourseId, courseId)
                .eq(StringUtils.isNotBlank(semester), Exam::getSemester, semester);
        PageHelper.startPage(pageNum, pageSize);
        List<Exam> exams = examMapper.selectList(lambdaQueryWrapper);
        PageInfo<Exam> pageInfo = new PageInfo<>(exams);
        return pageInfo;
    }

    @Override
    public List getStuExam(String stuId) {
        SysUser stu = managerFeignClient.getStu(stuId);
        if (stu == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        String className = stu.getClassName();
        Long classId = null;
        LambdaQueryWrapper<ExamClass> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ExamClass::getClassId, classId);
        List<ExamClass> examClasses = examClassMapper.selectList(lambdaQueryWrapper);
        List allExam = new ArrayList();
        for (ExamClass examClass : examClasses) {
            Long examId = examClass.getExamId();
            Exam exam = examMapper.selectById(examId);
            if (exam == null) {
                throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
            }
            Integer courseId = exam.getCourseId();
            Course course = courseMapper.selectById(courseId);
            long dd = 1000 * 24 * 60 * 60;//一天的毫秒数
            long hh = 1000 * 60 * 60;//一小时的毫秒数
            long mm = 1000 * 60;//一分钟的毫秒数
            //远程调用课程模块 设置课程名称 预留接口
            String examPublishTime = exam.getExamPublishTime();
            String examBeginTime = exam.getExamBeginTime();
            String examEndTime = exam.getExamEndTime();
            StuExamVo stuExamVo = BeanCopyUtils.copyBean(exam, StuExamVo.class);
            stuExamVo.setStuId(stuId);
            stuExamVo.setCourseName(course.getCourseName());
            long day = 0;
            long hour = 0;
            long min = 0;
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date publishTime = null;
            long current = Calendar.getInstance().getTimeInMillis();
            try {
                publishTime = df.parse(examPublishTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            try {
                if (current - publishTime.getTime() >= 0) {
                    examMapper.selectById(examId);
                    // 2. 时间类型转化
                    Date d1 = df.parse(examEndTime);
                    Date d2 = df.parse(examBeginTime);
                    // 3. 时间计算
                    long diff = d1.getTime() - d2.getTime();// 这样得到的差值是微秒级别
                    // 4. 对结果时间进行转化
                    if (diff / dd > 1) {
                        day = diff / dd;
                        hour = diff % dd / hh;
                        min = diff % dd % hh / mm;
                        String duration = (day) + "天" + hour + "时" + min + "分";
                        stuExamVo.setDuration(duration);
                    } else {
                        min = diff / mm;
                        String duration = min + "分";
                        stuExamVo.setDuration(duration);
                    }
                    if (current - publishTime.getTime() < 0) {
                        stuExamVo.setStatus(0);
                    } else if (current - publishTime.getTime() >= 0 && current - d2.getTime() < 0) {
                        stuExamVo.setStatus(1);
                    } else if (current - d2.getTime() > 0 && current - d1.getTime() < 0) {
                        stuExamVo.setStatus(2);
                    } else {
                        stuExamVo.setStatus(3);
                    }
                    allExam.add(stuExamVo);
                }
            } catch (Exception e) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
        }
        return allExam;
    }

    @Override
    public ExamStuVo getStuAnalyse(Long examId, List<Long> classIds) {
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        ExamStuVo examStuVo = BeanCopyUtils.copyBean(exam, ExamStuVo.class);
        List<Long> classIdss = examClassMapper.selectByExamId(examId);
        //所有学生的学号
        List<String> stuListByClass = new ArrayList<>();
        if (classIds != null) {
            //班级重构
            List<Classes> classes = null;
            for (Classes classes1 : classes) {
                String name = classes1.getName();
                List<String> stuListByClass1 = managerFeignClient.getStuListByClass(name);
                stuListByClass.addAll(stuListByClass1);
            }
        } else {
            //班级重构
            List<Classes> classes = null;
            for (Classes classes1 : classes) {
                String name = classes1.getName();
                List<String> stuListByClass1 = managerFeignClient.getStuListByClass(name);
                stuListByClass.addAll(stuListByClass1);
            }
        }
        //获取提交学生的Id
        List<String> stuIds = new ArrayList<>();
        //获取未提交学生的Id
        List<String> unsubmitStuIds = new ArrayList<>();
        //获取提交学生的成绩
        List<Float> stuIdScore = new ArrayList<>();
        //获取未提交学生的成绩集合
        List<Float> unsubmitStuIdScore = new ArrayList<>();
        LambdaQueryWrapper<StuAnswer> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StuAnswer::getExamId, examId);
        List<StuAnswer> stuAnswers = stuAnswerMapper.selectList(lambdaQueryWrapper);
        for (StuAnswer stuAnswer : stuAnswers) {
            String stuId = stuAnswer.getStuId();
            Integer epStatus = stuAnswer.getEpStatus();
            if (stuListByClass.contains(stuId) && epStatus > 0) {
                stuIds.add(stuId);
                stuIdScore.add(stuAnswer.getStuScore());
            } else {
                unsubmitStuIds.add(stuId);
                unsubmitStuIdScore.add(stuAnswer.getStuScore());
            }
        }
        //获取提交学生的全部信息
        List<SysUser> stuListByAllStuId = managerFeignClient.getStuListByAllStuId(stuIds);
        //获取未提交人数的全部信息
        List<SysUser> unsubmitStuListByAllStuId = managerFeignClient.getStuListByAllStuId(unsubmitStuIds);
        List<UserInfoStuVo> userInfoStuVos = BeanCopyUtils.copyBeanList(stuListByAllStuId, UserInfoStuVo.class);
        List<UserInfoStuVo> unsubmitUserInfoStuVos = BeanCopyUtils.copyBeanList(unsubmitStuListByAllStuId, UserInfoStuVo.class);
        int i = 0;
        int j = 0;
        for (UserInfoStuVo userInfoStuVo : userInfoStuVos) {
            userInfoStuVo.setStuScore(stuIdScore.get(i));
            i += 1;
        }
        System.out.println(userInfoStuVos.size());
        for (UserInfoStuVo unsubmitUserInfoStuVo : unsubmitUserInfoStuVos) {
            unsubmitUserInfoStuVo.setStuScore(unsubmitStuIdScore.get(j));
            j += 1;
        }
        examStuVo.setSubmitStu(userInfoStuVos);
        examStuVo.setUnSubmitStu(unsubmitUserInfoStuVos);
        Integer submitSize = userInfoStuVos.size();
        Integer size = userInfoStuVos.size() + unsubmitUserInfoStuVos.size();
        BigDecimal passRate = new BigDecimal((submitSize.doubleValue() / size.doubleValue()) * 100);
        passRate = passRate.setScale(0, BigDecimal.ROUND_HALF_UP);
        examStuVo.setPassRate(passRate.toString() + "%");
        return examStuVo;
    }

    @Override
    public StuExamScoreVo getStuScoreAnalyse(Long examId, Long classId) {
//        Classes classes = lassesMapper.selectById(classId);
        Classes classes = null;
        //获取试卷
        List<Long> epIds = examExampaperMapper.selectByExamId(examId);
        LambdaQueryWrapper<Exampaper> lambdaQueryWrapperEp = new LambdaQueryWrapper<>();
        lambdaQueryWrapperEp.in(Exampaper::getEpId, epIds);
        List<Exampaper> exampapers = exampaperMapper.selectList(lambdaQueryWrapperEp);
        //获取该班级的学生
        List<String> stuIds = managerFeignClient.getStuListByClass(classes.getName());
        List<Float> scores = new ArrayList<>();
        List<StuScoreVo> stuScoreVos = new ArrayList<>();
        for (Exampaper exampaper : exampapers) {
            //获取合格分数线
            Float qualifyScore = exampaper.getQualifyScore();
            Float epScore = exampaper.getEpScore();
            Long epId = exampaper.getEpId();
            LambdaQueryWrapper<StuAnswer> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StuAnswer::getExamId, examId)
                    .in(StuAnswer::getStuId, stuIds)
                    .eq(StuAnswer::getEpId, epId);
            List<StuAnswer> stuAnswers = stuAnswerMapper.selectList(lambdaQueryWrapper);
            for (StuAnswer stuAnswer : stuAnswers) {
                Float stuScore = stuAnswer.getStuScore();
                scores.add(stuScore); //获取当前学生的成绩
            }
            //成绩区间划分
            BigDecimal number = new BigDecimal(epScore);
            List<String> epScoreGrade = new ArrayList<>();
            epScoreGrade.add(number.multiply(new BigDecimal("0.0")) + "~" + number.multiply(new BigDecimal("0.2")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.2")) + "~" + number.multiply(new BigDecimal("0.4")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.4")) + "~" + number.multiply(new BigDecimal("0.6")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.6")) + "~" + number.multiply(new BigDecimal("0.8")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.8")) + "~" + number.multiply(new BigDecimal("1.0")));
            //成绩区间人数
            List<Integer> stuScoreGrade = new ArrayList<>();
            int a = 0, b = 0, c = 0, d = 0, f = 0;
            //计算班级考试平均分
            float allScore = 0;
            for (Float score : scores) {
                allScore += score;
                if (score >= epScore * 0.0 && score <= epScore * 0.2) {
                    a++;
                } else if (score > epScore * 0.2 && score <= epScore * 0.4) {
                    b++;
                } else if (score > epScore * 0.4 && score <= epScore * 0.6) {
                    c++;
                } else if (score > epScore * 0.6 && score <= epScore * 0.8) {
                    d++;
                } else {
                    f++;
                }
            }
            stuScoreGrade.add(a);
            stuScoreGrade.add(b);
            stuScoreGrade.add(c);
            stuScoreGrade.add(d);
            stuScoreGrade.add(f);
            BigDecimal avgStuScoreCount = new BigDecimal(allScore / scores.size());
            avgStuScoreCount = avgStuScoreCount.setScale(2, BigDecimal.ROUND_HALF_UP);
            //计算通过人数
            Integer passCount = c + d + f;
            Integer allCount = a + b + c + d + f;
            BigDecimal passRate = new BigDecimal((passCount / allCount) * 100);
            //小数点精度为2
            passRate = passRate.setScale(0, BigDecimal.ROUND_HALF_UP);
            StuScoreVo stuScoreVo = new StuScoreVo();
            stuScoreVo.setEpId(epId);
            stuScoreVo.setScoreList(epScoreGrade);
            stuScoreVo.setNumList(stuScoreGrade);
            stuScoreVo.setAverageScore(avgStuScoreCount);
            stuScoreVo.setPassRate(passRate);
            stuScoreVos.add(stuScoreVo);
        }
        StuExamScoreVo stuExamScoreVo = new StuExamScoreVo();
        stuExamScoreVo.setExamId(examId);
        stuExamScoreVo.setExamId(examId);
        stuExamScoreVo.setExamPaperScore(stuScoreVos);
        return stuExamScoreVo;
    }

    @Override
    public PageInfo<SysUser> getExamStuNum(Long examId, Integer pageNum, Integer pageSize) {
        List<Long> classIds = examClassMapper.selectByExamId(examId);
        List<String> classNames = new ArrayList<>();
        for (Long classId : classIds) {
            //班级重构
            List<String> className = null;
            classNames.addAll(className);
        }
        PageInfo<SysUser> stuListByClassName = managerFeignClient.getStuListByClassName(classNames, pageNum, pageSize);
        return stuListByClassName;
    }
}
